package client;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.Scanner;
import java.util.StringTokenizer;

public class Client extends Thread {
	public static final String TYPE_REGISTER = "R";
	public static final String TYPE_MESSAGE = "M";
	public static final String TYPE_ANSWER = "A";
	public static final String TYPE_ERROR = "E";
	public static final String TYPE_LOGUOT = "L";

	private String name;
	private Socket socket = null;
	private InputStream is = null;
	private OutputStream os = null;
	private String ipAddress = "localhost";
	private int port = 2222;
	private String des;

	public Client(String name, String des) {
		super();
		this.name = name;
		this.des = des;
	}
	
	public Client(String name) {
		super();
		this.name = name;
	}

	public void close() {
		try {
			sendLogout();
			if (socket != null) {
				socket.close();
			}
			System.exit(0);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void sendMessage(String content) {
		int index = content.indexOf(":");
		if (index == -1) {
			System.out.println("Tin nhan sai dinh dang");
			return;
		}
		String asd = content.substring(0, index);
		if (asd.indexOf("@") == -1) {
			System.out.println("Tin nhan sai dinh dang");
			return;
		}
		content = content.substring(index + 1);
		asd = asd.replace("@", "");
		asd = asd.replace(":", "");
		des = asd;
		String type = Client.TYPE_MESSAGE;
		StringBuffer sb = new StringBuffer();
		sb.append(type).append(";").append(name).append(";").append(des).append(";").append(content);
		byte[] bt = encode(sb.toString());
		if (os == null) {
			try {
				os = socket.getOutputStream();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		try {
			os.write(bt);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}


	public void receiveMessage() {
		if (is == null) {
			try {
				is = socket.getInputStream();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		try {
			byte[] bt = new byte[4];
			is.read(bt);
			int leng = ByteBuffer.wrap(bt).getInt();
			bt = new byte[leng];
			is.read(bt);
			String data = new String(bt);
			parseData(data);
		} catch (IOException e) {
			if (socket.isClosed()) {
				System.out.println("Ban da thoat thanh cong");
			} else
				e.printStackTrace();
		}
	}

	@Override
	public void run() {
		connect();
		sendRegister();
		receiveMessage();
		while (true) {
			if (socket.isClosed()) {
				break;
			}
			receiveMessage();
		}
	}

	public static void main(String[] args) {
		System.out.print("Nhap ten client: ");
		Scanner sc = new Scanner(System.in);
		String name = sc.next();
		System.out.println("Cu phap gui tin: @NguoiNhan: noi dung");
//		System.out.print("Nhap ten may can lien lac: ");
//		String des = sc.next();

//		Client cl = new Client(name, des);
		Client cl = new Client(name);
		cl.start();
		while (true) {
			String message = sc.nextLine();
			if (message == null || message.length() == 0) {
				continue;
			}
			if (message.equals("thoat")) {
				break;
			}
			cl.sendMessage(message);
		}
		cl.close();
	}
	
	private void connect() {
		try {
			socket = new Socket(ipAddress, port);
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	

	private void sendRegister() {
		String type = Client.TYPE_REGISTER;
		StringBuffer sb = new StringBuffer();
		sb.append(type).append(";").append(name).append(";").append("Server")
				.append(";").append("register");
		byte[] bt = encode(sb.toString());
		if (os == null) {
			try {
				os = socket.getOutputStream();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		try {
			os.write(bt);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	

	private void parseData(String data) {
		if (data == null || data.length() == 0) {
			return;
		}
		StringTokenizer st = new StringTokenizer(data, ";");
		String type = st.nextToken();
		String source = st.nextToken();
		String content = st.nextToken();
		if (type.equals(Client.TYPE_ANSWER)) {
			System.out.println(content);
		} else if (type.equals(Client.TYPE_ERROR)) {
			System.out.println(content);
		} else if (type.equals(Client.TYPE_MESSAGE)) {
			System.out.println(source + ": " + content);
		}
	}

	private byte[] encode(String data) {
		int leng = data.length();
		byte[] btLeng = ByteBuffer.allocate(4).putInt(leng).array();
		byte[] btData = data.getBytes();
		byte[] btResult = new byte[leng + 4];
		System.arraycopy(btLeng, 0, btResult, 0, 4);
		System.arraycopy(btData, 0, btResult, 4, leng);
		return btResult;
	}
	
	private void sendLogout(){
		String type = Client.TYPE_LOGUOT;
		StringBuffer sb = new StringBuffer();
		sb.append(type).append(";").append(name).append(";").append("Server")
				.append(";").append("register");
		byte[] bt = encode(sb.toString());
		if (os == null) {
			try {
				os = socket.getOutputStream();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		try {
			os.write(bt);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
